package view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Stack;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import model.App;

import panels.SPanel;

import jpcap.packet.ARPPacket;
import jpcap.packet.EthernetPacket;
import jpcap.packet.ICMPPacket;
import jpcap.packet.Packet;
import jpcap.packet.TCPPacket;
import jpcap.packet.UDPPacket;

public class PacketFrame extends JFrame {
	private static final long serialVersionUID = -3057315791452634234L;
	private int width = 600;
	private int height = 300;
	private Packet packet = null;

	public PacketFrame(Packet packet) {
		this.packet = packet;
		initUI();
		setTitle("SirusSniffer--Package");
		setSize(width, height);
		setLocationRelativeTo(null);
		setVisible(true);
		setResizable(false);
	}

	private void initUI() {
		SPanel main = new SPanel();
		main.setSize(width, height);
		Stack<String> strings = new Stack<String>();
		strings.push("      ");
		strings.push("概览:" + strings.get(0) + packet.toString());
		strings.push("目的MAC地址:" + strings.get(0)
				+ ((EthernetPacket) packet.datalink).getDestinationAddress());
		strings.push("源MAC地址:" + strings.get(0)
				+ ((EthernetPacket) packet.datalink).getSourceAddress());

		// ARP
		if (packet instanceof ARPPacket) {
			ARPPacket pt = (ARPPacket) packet;
			strings.push("目的IP地址：" + strings.get(0) + pt.getTargetProtocolAddress());
			strings.push("源IP地址：" + strings.get(0) + pt.getTargetProtocolAddress());
			strings.push("协议：" + strings.get(0) + "ARP");
			if (pt.operation == ARPPacket.ARP_REPLY)
				strings.push("ARP回复功能");
			else
				strings.push("ARP询问功能");
		}

		// ICMP
		if (packet instanceof ICMPPacket) {
			ICMPPacket pt = (ICMPPacket) packet;
			strings.push("目的IP地址：" + strings.get(0) + pt.dst_ip);
			strings.push("源IP地址：" + strings.get(0) + pt.src_ip);
			strings.push("协议：" + strings.get(0) + "ICMP");
			strings.push("type:" + strings.get(0) + pt.type);
			strings.push("code:" + strings.get(0) + pt.code);
			switch ((int) pt.type) {
			case 0:
				strings.push("ICMP具体含义：" + strings.get(0) + "回应请求");
				break;
			case 3:
				strings.push("ICMP具体含义：" + strings.get(0) + "数据包达不到接收端");
				break;
			case 4:
				strings.push("ICMP具体含义：" + strings.get(0) + "抑制从发送端传送来的数据");
				break;
			case 5:
				strings.push("ICMP具体含义：" + strings.get(0) + "请求路径变更");
				break;
			case 8:
				strings.push("ICMP具体含义：" + strings.get(0) + "响应请求");
				break;
			case 11:
				strings.push("ICMP具体含义：" + strings.get(0) + "通知发送端 TTL 已经为 0");
				break;
			case 12:
				strings.push("ICMP具体含义：" + strings.get(0) + "通知数据报形式出错");
				break;
			case 13:
				strings.push("ICMP具体含义：" + strings.get(0) + "要求对方送出时间信息");
				break;
			case 14:
				strings.push("ICMP具体含义：" + strings.get(0) + "对要求时间戳的响应");
				break;
			case 15:
				strings.push("ICMP具体含义：" + strings.get(0) + "向路由器查询地址等信息");
				break;
			case 16:
				strings.push("ICMP具体含义：" + strings.get(0) + "对查询信息的响应");
				break;
			case 17:
				strings.push("ICMP具体含义：" + strings.get(0) + "地址掩码请求消息");
				break;
			default:
				strings.push("ICMP具体含义：" + strings.get(0) + "查询不到");
				break;
			}
		}

		// TCP
		if (packet instanceof TCPPacket) {
			TCPPacket pt = (TCPPacket) packet;
			strings.push("目的IP地址：" + strings.get(0) + pt.dst_ip);
			strings.push("源IP地址：" + strings.get(0) + pt.src_ip);
			strings.push("协议：" + strings.get(0) + "TCP");
			strings.push("ack num:" + strings.get(0) + pt.ack_num);
			strings.push("接收端口：" + strings.get(0) + pt.dst_port);
			strings.push("发送端口：" + strings.get(0) + pt.src_port);
			// System.out.println("数据--------------------" + pt.data.length);
			// for (int i = 0; i < pt.data.length; i++) {
			// System.out.print((char) pt.data[i]);
			// }
			strings.push("数据：" + strings.get(0) + new String(pt.data));
		}

		// UDP
		if (packet instanceof UDPPacket) {
			UDPPacket pt = (UDPPacket) packet;
			strings.push("目的IP地址：" + strings.get(0) + pt.dst_ip);
			strings.push("源IP地址：" + strings.get(0) + pt.src_ip);
			strings.push("协议：" + strings.get(0) + "UDP");
			strings.push("");
			strings.push("接收端口：" + strings.get(0) + pt.dst_port);
			strings.push("发送端口：" + strings.get(0) + pt.src_port);
			// System.out.println("数据--------------------" + pt.data.length);
			// for (int i = 0; i < pt.data.length; i++) {
			// System.out.print((char) pt.data[i]);
			// }
			strings.push("数据：" + strings.get(0) + new String(pt.data));
		}

		// 放入
		JLabel tmpLabel = new JLabel(strings.get(1));
		SPanel tmPanel = null;
		JButton wholeBtn = new JButton("整合同源数据帧");
		main.setSize(width, height);
		main.add(tmpLabel);
		for (int i = 2; i < strings.size() - 1; i += 2) {
			tmPanel = new SPanel();
			tmpLabel = new JLabel(strings.get(i));
			tmPanel.add(tmpLabel);
			tmpLabel = new JLabel(strings.get(i + 1));
			tmPanel.add(tmpLabel);
			main.add(tmPanel);
		}
		if (strings.size() % 2 == 1) {
			tmpLabel = new JLabel(strings.peek());
			main.add(tmpLabel);
		}
		if (packet instanceof TCPPacket || packet instanceof UDPPacket)
			main.add(wholeBtn);
		// 设置大小--从父元素开始
		int size = 90 / main.getComponentCount();
		main.setCss(10, new int[] { size });
		for (int i = 0; i < main.getComponentCount(); i++) {
			if (main.getComponent(i) instanceof SPanel) {
				tmPanel = (SPanel) main.getComponent(i);
				tmPanel.setStyle(SPanel.VERTICAL);
				tmPanel.setCss(0, new int[] { 50 });
			}
		}
		add(main);

		wholeBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String answer = "";
				if (packet instanceof TCPPacket) {
					Packet pt = null;
					TCPPacket tmp = null;
					TCPPacket tar = (TCPPacket) packet;
					for (int i = 0; i < App.packetList.size(); i++) {
						pt = App.packetList.get(i);
						if (pt instanceof TCPPacket) {
							tmp = (TCPPacket) pt;
							if (tmp.dst_ip.equals(tar.dst_ip) && tmp.dst_port == tar.dst_port
									&& tmp.src_ip.equals(tar.src_ip)
									&& tmp.src_port == tar.src_port && tmp.ack_num == tar.ack_num) {
								try {
									String str = new String(tmp.data, "UTF-8");
									answer += str;
								} catch (UnsupportedEncodingException e1) {
									System.out.println("Error from byte to string");
								}
							}
						}
					}
				} else if (packet instanceof UDPPacket) {
					UDPPacket tar = (UDPPacket) packet;
					try {
						String str = new String(tar.data, "UTF-8");
						answer += str;
					} catch (UnsupportedEncodingException e1) {
						System.out.println("Error from byte to string");
					}
				}
				JFrame jf = new JFrame();
				JTextArea jta = new JTextArea();
				JScrollPane jsp = new JScrollPane(jta);
				jf.setTitle("SirusSniffer--Packet Combine");
				jf.setSize(width, height);
				jf.setLocationRelativeTo(null);
				jf.setVisible(true);
				jta.setText(answer);
				jta.setLineWrap(true);
				jf.add(jsp);
				/*
				 * if(answer.indexOf("gzip") >= 0) {
				 * System.out.println("yeah~~~~~");
				 * System.out.println("yeah~~~~~");
				 * System.out.println("yeah~~~~~"); byte[] data =
				 * unGZip(answer.substring(answer.indexOf("\n\r")).getBytes());
				 * try { System.out.println(new String(data, "UTF-8")); } catch
				 * (UnsupportedEncodingException e1) { e1.printStackTrace(); }
				 * 
				 * 
				 * // compressToByte(answer); //
				 * System.out.println("================\n\n\n\n\n\n\n"); //
				 * compressToByte(answer.substring(answer.indexOf("\r\n"))); //
				 * System.out.println("================\n\n\n\n\n\n\n"); //
				 * compressToByte(answer.substring(answer.indexOf("\n\r"))); }
				 */
			}
		});
	}

	public static void compressToByte(String str) {
		if (str == null || str.length() == 0) {
			return;
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		GZIPOutputStream gzip;
		try {
			gzip = new GZIPOutputStream(out);
			gzip.write(str.getBytes());
			gzip.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println(out);
	}

	public static byte[] unGZip(byte[] data) {
		byte[] b = null;
		try {
			ByteArrayInputStream bis = new ByteArrayInputStream(data);
			GZIPInputStream gzip = new GZIPInputStream(bis);
			byte[] buf = new byte[1024];
			int num = -1;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while ((num = gzip.read(buf, 0, buf.length)) != -1) {
				baos.write(buf, 0, num);
			}
			b = baos.toByteArray();
			baos.flush();
			baos.close();
			gzip.close();
			bis.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return b;
	}
}
